import React, { createContext, useContext, useState, useEffect, ReactNode } from 'react';
import { toast } from 'sonner@2.0.3';
import { DatabaseAPI, AuthAPI, ApiError } from '../api';
import { useI18n } from '../i18n/context';

export type DataSource = 'mock' | 'backend';

interface DatabaseInstance {
  id: string;
  name: string;
  engine: string;
  version: string;
  status: 'running' | 'stopped' | 'pending' | 'maintenance';
  region: string;
  instanceType: string;
  storage: number;
  connections: number;
  cpu: number;
  memory: number;
  createdAt: string;
}

interface SlowQuery {
  id: string;
  query: string;
  duration: number;
  database: string;
  timestamp: string;
  impact: 'high' | 'medium' | 'low';
}

interface DataSourceContextType {
  dataSource: DataSource;
  setDataSource: (source: DataSource) => void;
  isLoading: boolean;
  
  // Database operations
  databases: DatabaseInstance[];
  fetchDatabases: () => Promise<void>;
  createDatabase: (data: any) => Promise<DatabaseInstance>;
  updateDatabase: (id: string, data: any) => Promise<DatabaseInstance>;
  deleteDatabase: (id: string) => Promise<void>;
  startDatabase: (id: string) => Promise<DatabaseInstance>;
  stopDatabase: (id: string) => Promise<DatabaseInstance>;
  
  // Slow queries
  slowQueries: SlowQuery[];
  fetchSlowQueries: (databaseId?: string) => Promise<void>;
  killQuery: (queryId: string) => Promise<void>;
  optimizeQuery: (queryId: string) => Promise<{ suggestions: string[] }>;
}

// Mock data
const mockDatabases: DatabaseInstance[] = [
  {
    id: 'db-1',
    name: 'production-aurora',
    engine: 'Aurora PostgreSQL',
    version: '15.4',
    status: 'running',
    region: 'us-east-1',
    instanceType: 'db.r5.xlarge',
    storage: 250,
    connections: 45,
    cpu: 68,
    memory: 72,
    createdAt: '2024-01-15'
  },
  {
    id: 'db-2',
    name: 'analytics-mysql',
    engine: 'MySQL',
    version: '8.0.35',
    status: 'running',
    region: 'us-west-2',
    instanceType: 'db.r5.large',
    storage: 100,
    connections: 23,
    cpu: 42,
    memory: 38,
    createdAt: '2024-02-20'
  },
  {
    id: 'db-3',
    name: 'development-db',
    engine: 'PostgreSQL',
    version: '14.9',
    status: 'stopped',
    region: 'us-east-1',
    instanceType: 'db.t3.medium',
    storage: 50,
    connections: 0,
    cpu: 0,
    memory: 0,
    createdAt: '2024-03-10'
  }
];

const mockSlowQueries: SlowQuery[] = [
  {
    id: 'query-1',
    query: 'SELECT * FROM orders o JOIN users u ON o.user_id = u.id WHERE o.created_at > \'2024-01-01\' ORDER BY o.total_amount DESC',
    duration: 4.25,
    database: 'production-aurora',
    timestamp: '2024-03-15T10:30:00.000Z',
    impact: 'high'
  },
  {
    id: 'query-2',
    query: 'UPDATE user_sessions SET last_activity = NOW() WHERE user_id IN (SELECT id FROM users WHERE active = true)',
    duration: 2.15,
    database: 'analytics-mysql',
    timestamp: '2024-03-15T10:25:00.000Z',
    impact: 'medium'
  }
];

const DataSourceContext = createContext<DataSourceContextType | undefined>(undefined);

export const useDataSource = () => {
  const context = useContext(DataSourceContext);
  if (context === undefined) {
    throw new Error('useDataSource must be used within a DataSourceProvider');
  }
  return context;
};

interface DataSourceProviderProps {
  children: ReactNode;
}

export const DataSourceProvider: React.FC<DataSourceProviderProps> = ({ children }) => {
  const { t } = useI18n();
  const [dataSource, setDataSourceState] = useState<DataSource>(() => {
    const saved = localStorage.getItem('dataSource') as DataSource;
    return saved && ['mock', 'backend'].includes(saved) ? saved : 'mock';
  });
  
  const [isLoading, setIsLoading] = useState(false);
  const [databases, setDatabases] = useState<DatabaseInstance[]>(mockDatabases);
  const [slowQueries, setSlowQueries] = useState<SlowQuery[]>(mockSlowQueries);

  const setDataSource = (source: DataSource) => {
    setDataSourceState(source);
    localStorage.setItem('dataSource', source);
    
    // Reset data when switching sources
    if (source === 'mock') {
      setDatabases(mockDatabases);
      setSlowQueries(mockSlowQueries);
    } else {
      // Clear data and fetch from backend
      setDatabases([]);
      setSlowQueries([]);
      fetchDatabases();
      fetchSlowQueries();
    }
  };

  const handleApiError = (error: any, defaultMessage: string) => {
    console.error('API Error:', error);
    
    if (error instanceof ApiError) {
      if (error.status === 401) {
        toast.error(t.auth.errors.invalidCredentials);
      } else if (error.status >= 500) {
        toast.error(t.auth.errors.serverError);
      } else {
        toast.error(error.message || defaultMessage);
      }
    } else if (error.name === 'TypeError' && error.message.includes('fetch')) {
      toast.error(t.auth.errors.networkError);
    } else {
      toast.error(defaultMessage);
    }
  };

  // Database operations
  const fetchDatabases = async (): Promise<void> => {
    if (dataSource === 'mock') {
      setDatabases(mockDatabases);
      return;
    }

    setIsLoading(true);
    try {
      const response = await DatabaseAPI.getDatabases();
      setDatabases(response.data);
    } catch (error) {
      handleApiError(error, 'Failed to fetch databases');
      // Fallback to mock data on error
      setDatabases(mockDatabases);
    } finally {
      setIsLoading(false);
    }
  };

  const createDatabase = async (data: any): Promise<DatabaseInstance> => {
    if (dataSource === 'mock') {
      const newDatabase: DatabaseInstance = {
        ...data,
        id: `db-${Date.now()}`,
        status: 'pending' as const,
        connections: 0,
        cpu: 0,
        memory: 0,
        createdAt: new Date().toISOString()
      };
      
      setDatabases(prev => [...prev, newDatabase]);
      
      // Simulate status change
      setTimeout(() => {
        setDatabases(prev => 
          prev.map(db => 
            db.id === newDatabase.id 
              ? { ...db, status: 'running' as const, connections: Math.floor(Math.random() * 20), cpu: Math.floor(Math.random() * 50), memory: Math.floor(Math.random() * 60) }
              : db
          )
        );
      }, 3000);
      
      return newDatabase;
    }

    setIsLoading(true);
    try {
      const response = await DatabaseAPI.createDatabase(data);
      setDatabases(prev => [...prev, response.data]);
      return response.data;
    } catch (error) {
      handleApiError(error, 'Failed to create database');
      throw error;
    } finally {
      setIsLoading(false);
    }
  };

  const updateDatabase = async (id: string, data: any): Promise<DatabaseInstance> => {
    if (dataSource === 'mock') {
      const updatedDb = { ...databases.find(db => db.id === id), ...data };
      setDatabases(prev => prev.map(db => db.id === id ? updatedDb : db));
      return updatedDb as DatabaseInstance;
    }

    setIsLoading(true);
    try {
      const response = await DatabaseAPI.updateDatabase(id, data);
      setDatabases(prev => prev.map(db => db.id === id ? response.data : db));
      return response.data;
    } catch (error) {
      handleApiError(error, 'Failed to update database');
      throw error;
    } finally {
      setIsLoading(false);
    }
  };

  const deleteDatabase = async (id: string): Promise<void> => {
    if (dataSource === 'mock') {
      setDatabases(prev => prev.filter(db => db.id !== id));
      return;
    }

    setIsLoading(true);
    try {
      await DatabaseAPI.deleteDatabase(id);
      setDatabases(prev => prev.filter(db => db.id !== id));
    } catch (error) {
      handleApiError(error, 'Failed to delete database');
      throw error;
    } finally {
      setIsLoading(false);
    }
  };

  const startDatabase = async (id: string): Promise<DatabaseInstance> => {
    if (dataSource === 'mock') {
      const updatedDb = { 
        ...databases.find(db => db.id === id)!, 
        status: 'running' as const,
        connections: Math.floor(Math.random() * 20) + 5,
        cpu: Math.floor(Math.random() * 50) + 10,
        memory: Math.floor(Math.random() * 60) + 20
      };
      setDatabases(prev => prev.map(db => db.id === id ? updatedDb : db));
      return updatedDb;
    }

    setIsLoading(true);
    try {
      const response = await DatabaseAPI.startDatabase(id);
      setDatabases(prev => prev.map(db => db.id === id ? response.data : db));
      return response.data;
    } catch (error) {
      handleApiError(error, 'Failed to start database');
      throw error;
    } finally {
      setIsLoading(false);
    }
  };

  const stopDatabase = async (id: string): Promise<DatabaseInstance> => {
    if (dataSource === 'mock') {
      const updatedDb = { 
        ...databases.find(db => db.id === id)!, 
        status: 'stopped' as const, 
        connections: 0, 
        cpu: 0, 
        memory: 0 
      };
      setDatabases(prev => prev.map(db => db.id === id ? updatedDb : db));
      return updatedDb;
    }

    setIsLoading(true);
    try {
      const response = await DatabaseAPI.stopDatabase(id);
      setDatabases(prev => prev.map(db => db.id === id ? response.data : db));
      return response.data;
    } catch (error) {
      handleApiError(error, 'Failed to stop database');
      throw error;
    } finally {
      setIsLoading(false);
    }
  };

  // Slow queries operations
  const fetchSlowQueries = async (databaseId?: string): Promise<void> => {
    if (dataSource === 'mock') {
      setSlowQueries(mockSlowQueries);
      return;
    }

    setIsLoading(true);
    try {
      const response = await DatabaseAPI.getSlowQueries(databaseId);
      setSlowQueries(response.data);
    } catch (error) {
      handleApiError(error, 'Failed to fetch slow queries');
      setSlowQueries(mockSlowQueries);
    } finally {
      setIsLoading(false);
    }
  };

  const killQuery = async (queryId: string): Promise<void> => {
    if (dataSource === 'mock') {
      setSlowQueries(prev => prev.filter(q => q.id !== queryId));
      return;
    }

    setIsLoading(true);
    try {
      await DatabaseAPI.killQuery(queryId);
      setSlowQueries(prev => prev.filter(q => q.id !== queryId));
    } catch (error) {
      handleApiError(error, 'Failed to kill query');
      throw error;
    } finally {
      setIsLoading(false);
    }
  };

  const optimizeQuery = async (queryId: string): Promise<{ suggestions: string[] }> => {
    if (dataSource === 'mock') {
      return {
        suggestions: [
          'Add an index on the user_id column',
          'Consider using LIMIT to reduce result set size',
          'Replace SELECT * with specific column names'
        ]
      };
    }

    setIsLoading(true);
    try {
      const response = await DatabaseAPI.optimizeQuery(queryId);
      return response.data;
    } catch (error) {
      handleApiError(error, 'Failed to optimize query');
      throw error;
    } finally {
      setIsLoading(false);
    }
  };

  // Initialize data on mount
  useEffect(() => {
    if (dataSource === 'backend') {
      // Only fetch if user is authenticated
      const token = localStorage.getItem('db_console_token');
      if (token) {
        fetchDatabases();
        fetchSlowQueries();
      }
    }
  }, [dataSource]);

  const value: DataSourceContextType = {
    dataSource,
    setDataSource,
    isLoading,
    databases,
    fetchDatabases,
    createDatabase,
    updateDatabase,
    deleteDatabase,
    startDatabase,
    stopDatabase,
    slowQueries,
    fetchSlowQueries,
    killQuery,
    optimizeQuery
  };

  return (
    <DataSourceContext.Provider value={value}>
      {children}
    </DataSourceContext.Provider>
  );
};